######################################################## -*- coding: utf-8 -*-
# 
# collector.py
#
# Collect daily or other data from internet, and store them into database,
# using method provided from module 'db' and 'utils'
# We assume database and tables are ready.
# 
##############################################################################
import datetime
from db import Stock
import utils

YEAR_2000 = 2000

class RawDataManager(object):
    def __init__(self, dbobj):
        """ A class responsable for stock.td_%code and stock.status table
            dbobj - a db object passed from outside
        """
        self.db = dbobj
        pass
    
    def fill(self, code):
        """ Fill stock.td_%code
        """
        self.update_status()
        pass

    def get_status(self):
        """ Read status from table stock.status
        """
        pass
    
    def update_status(self):
        """ Update the cooresponding status bit in table stock.status
        """
        pass
    
class StockInfoManager(object):
    def __init__(self, dbobj):
        """ A class responsable for stock.info table
            dbobj - a db object passed from outside
        """
        self.db = dbobj
        pass

    def fill(self):
        pass
    
class StatusManager(object):
    def __init__(self, dbobj):
        """ A class used to manage stock.status
        """
        self.db = dbobj
        pass

    def has_data(self, code, date):
        """ Return True if the `day` has raw data downloaded, else
            return False
        """
        year  = date.year
        month = date.month
        day   = date.day
        month_status = self.db.get_status_column(month)
        sql_query = """SELECT `code`, `year`, `status`, `%s` FROM `%s`
                             WHERE `id` = '%s';
                    """%(month_status, self.db.table_status, code+'_%d'%year)
        self.db.cursor.execute(sql_query)
        r = self.db.cursor.fetchone()
        if r == None:
            print('stock %s has no entry')
        

    def maintain(self):
        """ Read data from stock.info and fill stock.status table.
            Maintain stock.status table, this function will check
            all `code`, `ipo_date`, `last_date` in stock.info and
            compare `ipo_date` with YEAR to get the bigger one.
        """
        this_year = datetime.date.today().year
        done = True
        sql_query = \
          "SELECT `code`, `ipo_date`, `last_date` FROM `%s`;"%self.db.table_info
        self.db.cursor.execute(sql_query)
        for r in self.db.cursor.fetchall():
            if r[1] == None:    # if no ipo_date
                done = False
                continue

            begin_year = int(r[1][:4]) # set begin year to ipo_date
            if begin_year < YEAR_2000:
                begin_year = YEAR_2000 # we only collect data since 2000

            # default end year is current year, but some stock may be
            # suspended cross years
            end_year = this_year
            if r[2] != None: 
                end_year = int(r[2][:4])

            code = r[0]
            # TODO: should be partial update, not insert.
            # insert r[0] * (end_year - begin_year) rows for each stock
            for year in range(begin_year, end_year+1):
                
                sql_query  = """SELECT COUNT(*) FROM `%s` WHERE `id` = '%s';
                             """%(self.db.table_status, code+'_%d'%year)
                self.db.cursor.execute(sql_query)
                
                if self.db.cursor.fetchone()[0] == 0:
                    sql_insert = """INSERT INTO `%s`
                                    (`id`, `code`, `year`, `status`)
                                    VALUES
                                    ('%s', '%s', %d, %d);
                                 """%(self.db.table_status, code+'_%d'%year,
                                      code, year, 0)
                    self.db.cursor.execute(sql_insert)


        if done == False:
            utils.warning('Not all stock status be updated')

        return done

